Make the event-channel pending and mask arrays consist of
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Mon, 17 Oct 2005 14:15:17 +0000 (15:15 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Mon, 17 Oct 2005 14:15:17 +0000 (15:15 +0100)
longs. Thi sensures appropriate alignment for architectures
that require it, and also allows us to naturally support up
to 4096 event channels per 64-bit guest.

Moved 'n_vcpu' field from shared_info to start_info. Really it
ought to disappear altogether as the info can be derived from
xenstore.

Fix a weird bug in XendDomainInfo where 'vcpus' information for
a domain defaults to floating point value 1.0 rather than integer
1. This looks like a Python bug to me, but in any case it is
'fixed' by explicitly converting the default value to an integer.

Signed-off-by: Keir Fraser <keir@xensource.com>
17 files changed:
linux-2.6-xen-sparse/arch/ia64/xen/drivers/evtchn_ia64.c
linux-2.6-xen-sparse/arch/xen/i386/kernel/smpboot.c
linux-2.6-xen-sparse/arch/xen/kernel/evtchn.c
linux-2.6-xen-sparse/arch/xen/x86_64/kernel/smpboot.c
linux-2.6-xen-sparse/include/asm-xen/asm-i386/mach-xen/smpboot_hooks.h
linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/mach-xen/smpboot_hooks.h
linux-2.6-xen-sparse/include/asm-xen/evtchn.h
tools/libxc/xc_linux_build.c
tools/libxc/xc_vmx_build.c
tools/python/xen/xend/XendDomainInfo.py
xen/arch/ia64/vmx/vmx_support.c
xen/arch/x86/domain_build.c
xen/arch/x86/vmx_io.c
xen/common/keyhandler.c
xen/include/public/xen.h
xen/include/xen/event.h
xen/include/xen/sched.h

index bd576ce8695af4d6dba5fdcdf882cbc8baec57c4..0027b82a6243416d1fad3edb7e8ea2a4419800db 100644 (file)
@@ -94,7 +94,7 @@ void notify_remote_via_irq(int irq)
 
 irqreturn_t evtchn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 {
-    u32            l1, l2;
+    unsigned long  l1, l2;
     unsigned int   l1i, l2i, port;
     irqreturn_t (*handler)(int, void *, struct pt_regs *);
     shared_info_t *s = HYPERVISOR_shared_info;
@@ -108,14 +108,14 @@ irqreturn_t evtchn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
     while ( l1 != 0 )
     {
         l1i = __ffs(l1);
-        l1 &= ~(1 << l1i);
+        l1 &= ~(1UL << l1i);
 
         while ( (l2 = s->evtchn_pending[l1i] & ~s->evtchn_mask[l1i]) != 0 )
         {
             l2i = __ffs(l2);
-            l2 &= ~(1 << l2i);
+            l2 &= ~(1UL << l2i);
 
-            port = (l1i << 5) + l2i;
+            port = (l1i * BITS_PER_LONG) + l2i;
             if ( (handler = evtchns[port].handler) != NULL )
            {
                clear_evtchn(port);
index b13abf720e27498d864bbf750635564ba30d97b2..01e245e3ab5acbc105ecb1ed1f68ebfa57b7f33f 100644 (file)
@@ -1123,7 +1123,7 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
         * If SMP should be disabled, then really disable it!
         */
        if (!max_cpus) {
-               HYPERVISOR_shared_info->n_vcpu = 1;
+               xen_start_info->n_vcpu = 1;
                printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n");
                smpboot_clear_io_apic_irqs();
 #if 0
@@ -1153,12 +1153,10 @@ static void __init smp_boot_cpus(unsigned int max_cpus)
         */
        Dprintk("CPU present map: %lx\n", physids_coerce(phys_cpu_present_map));
 #endif
-       Dprintk("CPU present map: %lx\n",
-               (1UL << HYPERVISOR_shared_info->n_vcpu) - 1);
+       Dprintk("CPU present map: %lx\n", (1UL << xen_start_info->n_vcpu) - 1);
 
        kicked = 1;
-       for (cpu = 1; kicked < NR_CPUS &&
-                    cpu < HYPERVISOR_shared_info->n_vcpu; cpu++) {
+       for (cpu = 1; kicked < NR_CPUS && cpu < xen_start_info->n_vcpu; cpu++) {
                if (max_cpus <= cpucount+1)
                        continue;
 
index 80e017684bd809692f46e5442b21dbb59103f2bd..1d27f11910741ab35b732003ff0ad6c937ea6611 100644 (file)
@@ -71,8 +71,8 @@ static unsigned long pirq_needs_unmask_notify[NR_PIRQS/sizeof(unsigned long)];
 
 #ifdef CONFIG_SMP
 
-static u8  cpu_evtchn[NR_EVENT_CHANNELS];
-static u32 cpu_evtchn_mask[NR_CPUS][NR_EVENT_CHANNELS/32];
+static u8 cpu_evtchn[NR_EVENT_CHANNELS];
+static unsigned long cpu_evtchn_mask[NR_CPUS][NR_EVENT_CHANNELS/BITS_PER_LONG];
 
 #define active_evtchns(cpu,sh,idx)             \
        ((sh)->evtchn_pending[idx] &            \
@@ -137,7 +137,7 @@ EXPORT_SYMBOL(force_evtchn_callback);
 /* NB. Interrupts are disabled on entry. */
 asmlinkage void evtchn_do_upcall(struct pt_regs *regs)
 {
-       u32     l1, l2;
+       unsigned long  l1, l2;
        unsigned int   l1i, l2i, port;
        int            irq, cpu = smp_processor_id();
        shared_info_t *s = HYPERVISOR_shared_info;
@@ -149,13 +149,13 @@ asmlinkage void evtchn_do_upcall(struct pt_regs *regs)
        l1 = xchg(&vcpu_info->evtchn_pending_sel, 0);
        while (l1 != 0) {
                l1i = __ffs(l1);
-               l1 &= ~(1 << l1i);
+               l1 &= ~(1UL << l1i);
         
                while ((l2 = active_evtchns(cpu, s, l1i)) != 0) {
                        l2i = __ffs(l2);
-                       l2 &= ~(1 << l2i);
+                       l2 &= ~(1UL << l2i);
             
-                       port = (l1i << 5) + l2i;
+                       port = (l1i * BITS_PER_LONG) + l2i;
                        if ((irq = evtchn_to_irq[port]) != -1)
                                do_IRQ(irq, regs);
                        else
index 48abf1150764b4b9d2b4e38aa8f4c3c68b5b3969..b48b559a45f81ccc9dbcf80a6485e54ba2a1b7bc 100644 (file)
@@ -1045,7 +1045,7 @@ static int __cpuinit smp_sanity_check(unsigned max_cpus)
         */
        if (!max_cpus) {
 #ifdef CONFIG_XEN
-               HYPERVISOR_shared_info->n_vcpu = 1;
+               xen_start_info->n_vcpu = 1;
 #endif
                printk(KERN_INFO "SMP mode deactivated, forcing use of dummy APIC emulation.\n");
 #ifndef CONFIG_XEN
@@ -1082,7 +1082,7 @@ void __cpuinit smp_prepare_cpus(unsigned int max_cpus)
                int apicid = cpu_present_to_apicid(i);
                if (physid_isset(apicid, phys_cpu_present_map)) {
 #else
-               if (i < HYPERVISOR_shared_info->n_vcpu) {
+               if (i < xen_start_info->n_vcpu) {
 #endif
                        cpu_set(i, cpu_present_map);
                        /* possible map would be different if we supported real
index 28adeaf2447e0ea227daa98389a79941c52024ad..fa85aa2cfe0ec67c6bfe562e3d1f0da0402b2ae8 100644 (file)
@@ -52,4 +52,4 @@ static inline void smpboot_setup_io_apic(void)
 }
 
 
-#define        smp_found_config        (HYPERVISOR_shared_info->n_vcpu > 1)
+#define        smp_found_config        (xen_start_info->n_vcpu > 1)
index 28adeaf2447e0ea227daa98389a79941c52024ad..fa85aa2cfe0ec67c6bfe562e3d1f0da0402b2ae8 100644 (file)
@@ -52,4 +52,4 @@ static inline void smpboot_setup_io_apic(void)
 }
 
 
-#define        smp_found_config        (HYPERVISOR_shared_info->n_vcpu > 1)
+#define        smp_found_config        (xen_start_info->n_vcpu > 1)
index f2523926d80f8e1a25ed068da45f9c9f883a3636..127cf8e72f10918d1786d9396ff92385cdfba660 100644 (file)
@@ -99,8 +99,9 @@ static inline void unmask_evtchn(int port)
         * like a real IO-APIC we 'lose the interrupt edge' if the channel is
         * masked.
         */
-       if (synch_test_bit         (port,    &s->evtchn_pending[0]) && 
-           !synch_test_and_set_bit(port>>5, &vcpu_info->evtchn_pending_sel)) {
+       if (synch_test_bit(port, &s->evtchn_pending[0]) && 
+           !synch_test_and_set_bit(port / BITS_PER_LONG,
+                                   &vcpu_info->evtchn_pending_sel)) {
                vcpu_info->evtchn_upcall_pending = 1;
                if (!vcpu_info->evtchn_upcall_mask)
                        force_evtchn_callback();
index 5cdb568bc0126bc48e9add73bb7c9a1a942382b2..1185fc020e9cf925201630bd4503c1b605e4dfbb 100644 (file)
@@ -636,6 +636,7 @@ static int setup_guest(int xc_handle,
     start_info->store_evtchn = store_evtchn;
     start_info->console_mfn   = *console_mfn;
     start_info->console_evtchn = console_evtchn;
+    start_info->n_vcpu       = vcpus;
     if ( initrd_len != 0 )
     {
         start_info->mod_start    = vinitrd_start;
@@ -653,9 +654,6 @@ static int setup_guest(int xc_handle,
     for ( i = 0; i < MAX_VIRT_CPUS; i++ )
         shared_info->vcpu_data[i].evtchn_upcall_mask = 1;
 
-    shared_info->n_vcpu = vcpus;
-    printf(" VCPUS:         %d\n", shared_info->n_vcpu);
-
     munmap(shared_info, PAGE_SIZE);
 
     /* Send the page update requests down to the hypervisor. */
index 5dd55e94f7de354e71289a22b36f5812d47ab4c3..2f8a5ec72da67c02879a49b56b88327ecd5bcc68 100644 (file)
@@ -519,9 +519,6 @@ static int setup_guest(int xc_handle,
     for ( i = 0; i < MAX_VIRT_CPUS; i++ )
         shared_info->vcpu_data[i].evtchn_upcall_mask = 1;
 
-    shared_info->n_vcpu = vcpus;
-    printf(" VCPUS:         %d\n", shared_info->n_vcpu);
-
     munmap(shared_info, PAGE_SIZE);
 
     /* Populate the event channel port in the shared page */
index 79fdd38a9ada176834fde3806af4cc9ee2329125..3615aed8d904b18f386dd40ca869b47485d554a0 100644 (file)
@@ -439,7 +439,7 @@ class XendDomainInfo:
             defaultInfo('on_crash',     lambda: "restart")
             defaultInfo('cpu',          lambda: None)
             defaultInfo('cpu_weight',   lambda: 1.0)
-            defaultInfo('vcpus',        lambda: 1)
+            defaultInfo('vcpus',        lambda: int(1))
             defaultInfo('vcpu_avail',   lambda: (1 << self.info['vcpus']) - 1)
             defaultInfo('bootloader',   lambda: None)
             defaultInfo('backend',      lambda: [])
index afd0f650d029f54b6a61e22bb98e5b74b9386adb..4da31f23328ee35422057ce74db39578f7fa8182 100644 (file)
@@ -49,7 +49,7 @@ void vmx_wait_io(void)
          */
        if (test_and_clear_bit(port,
                &d->shared_info->evtchn_pending[0])) {
-           clear_bit(port>>5, &v->vcpu_info->evtchn_pending_sel);
+           clear_bit(port/BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel);
            clear_bit(0, &v->vcpu_info->evtchn_upcall_pending);
            vmx_io_assist(v);
        }
@@ -67,7 +67,7 @@ void vmx_wait_io(void)
             * nothing losed. Next loop will check I/O channel to fix this
             * window.
             */
-           clear_bit(port>>5, &v->vcpu_info->evtchn_pending_sel);
+           clear_bit(port/BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel);
        }
        else
            break;
@@ -139,8 +139,8 @@ void vmx_intr_assist(struct vcpu *v)
     /* Clear indicator specific to interrupt delivered from DM */
     if (test_and_clear_bit(port,
                &d->shared_info->evtchn_pending[0])) {
-       if (!d->shared_info->evtchn_pending[port >> 5])
-           clear_bit(port>>5, &v->vcpu_info->evtchn_pending_sel);
+       if (!d->shared_info->evtchn_pending[port/BITS_PER_LONG])
+           clear_bit(port/BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel);
 
        if (!v->vcpu_info->evtchn_pending_sel)
            clear_bit(0, &v->vcpu_info->evtchn_upcall_pending);
index 69b0ddd58b61959fc91dbdc4a65941809ba4db61..38a3cb2c999b24445c422dca3ceb5e90c653b00d 100644 (file)
@@ -557,10 +557,9 @@ int construct_dom0(struct domain *d,
     /* Mask all upcalls... */
     for ( i = 0; i < MAX_VIRT_CPUS; i++ )
         d->shared_info->vcpu_data[i].evtchn_upcall_mask = 1;
-    d->shared_info->n_vcpu = num_online_cpus();
 
-    for ( i = 1; i < d->shared_info->n_vcpu; i++ )
-        (void)alloc_vcpu(d, i, i % num_online_cpus());
+    for ( i = 1; i < num_online_cpus(); i++ )
+        (void)alloc_vcpu(d, i, i);
 
     /* Set up monitor table */
     update_pagetables(v);
@@ -588,7 +587,8 @@ int construct_dom0(struct domain *d,
     /* Set up start info area. */
     si = (start_info_t *)vstartinfo_start;
     memset(si, 0, PAGE_SIZE);
-    si->nr_pages     = nr_pages;
+    si->nr_pages = nr_pages;
+    si->n_vcpu   = num_online_cpus();
 
     if ( opt_dom0_translate )
     {
index 1d904e43a9bdc6c0d684c9fff49726023037f7aa..e6536b31a1613e806cf2ee6d5be1ad966b38dcbc 100644 (file)
@@ -684,15 +684,15 @@ int vmx_clear_pending_io_event(struct vcpu *v)
     struct domain *d = v->domain;
     int port = iopacket_port(d);
 
-    /* evtchn_pending is shared by other event channels in 0-31 range */
-    if (!d->shared_info->evtchn_pending[port>>5])
-        clear_bit(port>>5, &v->vcpu_info->evtchn_pending_sel);
+    /* evtchn_pending_sel bit is shared by other event channels. */
+    if (!d->shared_info->evtchn_pending[port/BITS_PER_LONG])
+        clear_bit(port/BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel);
 
-    /* Note: VMX domains may need upcalls as well */
+    /* Note: VMX domains may need upcalls as well. */
     if (!v->vcpu_info->evtchn_pending_sel)
         clear_bit(0, &v->vcpu_info->evtchn_upcall_pending);
 
-    /* clear the pending bit for port */
+    /* Clear the pending bit for port. */
     return test_and_clear_bit(port, &d->shared_info->evtchn_pending[0]);
 }
 
@@ -726,7 +726,7 @@ void vmx_wait_io()
             break;
         /* Events other than IOPACKET_PORT might have woken us up. In that
            case, safely go back to sleep. */
-        clear_bit(port>>5, &current->vcpu_info->evtchn_pending_sel);
+        clear_bit(port/BITS_PER_LONG, &current->vcpu_info->evtchn_pending_sel);
         clear_bit(0, &current->vcpu_info->evtchn_upcall_pending);
     } while(1);
 }
index 0f1bbb98721f631d51bca7d911ff0a2cf8d86eff..acbfd094bc2f2eb397c39b0f79ebf38385c42fee 100644 (file)
@@ -136,7 +136,7 @@ static void do_task_queues(unsigned char key)
                             &d->shared_info->evtchn_pending[0]),
                    test_bit(v->virq_to_evtchn[VIRQ_DEBUG], 
                             &d->shared_info->evtchn_mask[0]),
-                   test_bit(v->virq_to_evtchn[VIRQ_DEBUG]>>5
+                   test_bit(v->virq_to_evtchn[VIRQ_DEBUG]/BITS_PER_LONG
                             &v->vcpu_info->evtchn_pending_sel));
             send_guest_virq(v, VIRQ_DEBUG);
         }
index c0111b50271b5f3f1c75a8de2ddd019837bef21a..3c2d0094f24cdeaf0e3ed25686ee10ec42dc0ae7 100644 (file)
@@ -260,8 +260,11 @@ typedef struct
     unsigned long args[6];
 } multicall_entry_t;
 
-/* Event channel endpoints per domain. */
-#define NR_EVENT_CHANNELS 1024
+/*
+ * Event channel endpoints per domain:
+ *  1024 if a long is 32 bits; 4096 if a long is 64 bits.
+ */
+#define NR_EVENT_CHANNELS (sizeof(unsigned long) * sizeof(unsigned long) * 64)
 
 /*
  * Per-VCPU information goes here. This will be cleaned up more when Xen 
@@ -295,7 +298,7 @@ typedef struct vcpu_info {
      */
     uint8_t evtchn_upcall_pending;
     uint8_t evtchn_upcall_mask;
-    uint32_t evtchn_pending_sel;
+    unsigned long evtchn_pending_sel;
 #ifdef __ARCH_HAS_VCPU_INFO
     arch_vcpu_info_t arch;
 #endif
@@ -333,16 +336,14 @@ typedef struct shared_info {
 
     vcpu_time_info_t vcpu_time[MAX_VIRT_CPUS];
 
-    uint32_t n_vcpu;
-
     /*
-     * A domain can have up to 1024 "event channels" on which it can send
-     * and receive asynchronous event notifications. There are three classes
-     * of event that are delivered by this mechanism:
+     * A domain can create "event channels" on which it can send and receive
+     * asynchronous event notifications. There are three classes of event that
+     * are delivered by this mechanism:
      *  1. Bi-directional inter- and intra-domain connections. Domains must
-     *     arrange out-of-band to set up a connection (usually the setup
-     *     is initiated and organised by a privileged third party such as
-     *     software running in domain 0).
+     *     arrange out-of-band to set up a connection (usually by allocating
+     *     an unbound 'listener' port and avertising that via a storage service
+     *     such as xenstore).
      *  2. Physical interrupts. A domain with suitable hardware-access
      *     privileges can bind an event-channel port to a physical interrupt
      *     source.
@@ -350,8 +351,8 @@ typedef struct shared_info {
      *     port to a virtual interrupt source, such as the virtual-timer
      *     device or the emergency console.
      * 
-     * Event channels are addressed by a "port index" between 0 and 1023.
-     * Each channel is associated with two bits of information:
+     * Event channels are addressed by a "port index". Each channel is
+     * associated with two bits of information:
      *  1. PENDING -- notifies the domain that there is a pending notification
      *     to be processed. This bit is cleared by the guest.
      *  2. MASK -- if this bit is clear then a 0->1 transition of PENDING
@@ -363,11 +364,11 @@ typedef struct shared_info {
      * 
      * To expedite scanning of pending notifications, any 0->1 pending
      * transition on an unmasked channel causes a corresponding bit in a
-     * 32-bit selector to be set. Each bit in the selector covers a 32-bit
-     * word in the PENDING bitfield array.
+     * per-vcpu selector word to be set. Each bit in the selector covers a
+     * 'C long' in the PENDING bitfield array.
      */
-    uint32_t evtchn_pending[32];
-    uint32_t evtchn_mask[32];
+    unsigned long evtchn_pending[sizeof(unsigned long) * 8];
+    unsigned long evtchn_mask[sizeof(unsigned long) * 8];
 
     /*
      * Wallclock time: updated only by control software. Guests should base
@@ -422,6 +423,7 @@ typedef struct start_info {
     unsigned long mfn_list;     /* VIRTUAL address of page-frame list.    */
     unsigned long mod_start;    /* VIRTUAL address of pre-loaded module.  */
     unsigned long mod_len;      /* Size (bytes) of pre-loaded module.     */
+    uint32_t n_vcpu;
     int8_t cmd_line[MAX_GUEST_CMDLINE];
 } start_info_t;
 
index 8f527b0c83948f363c0b92f9fb64246a76e2732c..e8a8bc2b5bc55f89604e67977b698c538e3c31dc 100644 (file)
@@ -28,10 +28,11 @@ static inline void evtchn_set_pending(struct vcpu *v, int port)
     shared_info_t *s = d->shared_info;
 
     /* These four operations must happen in strict order. */
-    if ( !test_and_set_bit(port,    &s->evtchn_pending[0]) &&
-         !test_bit        (port,    &s->evtchn_mask[0])    &&
-         !test_and_set_bit(port>>5, &v->vcpu_info->evtchn_pending_sel) &&
-         !test_and_set_bit(0,       &v->vcpu_info->evtchn_upcall_pending) )
+    if ( !test_and_set_bit(port, &s->evtchn_pending[0]) &&
+         !test_bit        (port, &s->evtchn_mask[0])    &&
+         !test_and_set_bit(port / BITS_PER_LONG,
+                           &v->vcpu_info->evtchn_pending_sel) &&
+         !test_and_set_bit(0, &v->vcpu_info->evtchn_upcall_pending) )
     {
         evtchn_notify(v);
     }
index 42502052684d27375027f361450cf0a4f813386a..0f012456af4523ab23ad192eb607e6f0724f35ab 100644 (file)
@@ -19,7 +19,7 @@ extern rwlock_t domlist_lock;
 /* A global pointer to the initial domain (DOM0). */
 extern struct domain *dom0;
 
-#define MAX_EVTCHNS        1024
+#define MAX_EVTCHNS        NR_EVENT_CHANNELS
 #define EVTCHNS_PER_BUCKET 128
 #define NR_EVTCHN_BUCKETS  (MAX_EVTCHNS / EVTCHNS_PER_BUCKET)